/**
  @author: cilang
  @qq: 1019383856
  @bili: https://space.bilibili.com/433915419
  @gitee: https://gitee.com/OpencvLZG
  @since: 2023/4/21
  @desc: //TODO
**/

package main

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"net/http"
)

//type Hub struct {
//	UserId string
//	Conn   chan []*websocket.Conn
//}

// Hub Manage WsConnects
var Hub = make(map[string]*websocket.Conn)

// HubGroup Manage Group {Key:GroupId,Value:SocketConnects}
var HubGroup = make(map[string][]*websocket.Conn)

// SenderMsg Sender Message
type SenderMsg struct {
	UserId   string `json:"user_id,required"`
	Receptor string `json:"receptor,omitempty"`
	RoomId   string `json:"room_id,omitempty"`
	Msg      string `json:"msg,required"`
	Type     string `json:"type,omitempty"`
}

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

func WsHandle(c *gin.Context) {
	ws, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Fatal(err)
	}

	userId := c.Query("user_id")
	Hub[userId] = ws
	go ChatHandle(ws)

}
func JoinGroup(c *gin.Context) {
	userId := c.Query("user_id")
	groupId := c.Query("group_id")
	wsConn, ok := Hub[userId]
	if !ok {
		c.JSON(http.StatusOK, gin.H{"message": "User Is Not Online"})
		return
	}
	HubGroup[groupId] = append(HubGroup[groupId], wsConn)
	c.JSON(http.StatusOK, gin.H{"message": "Join Chat Group Successful"})

}
func ChatHandle(ws *websocket.Conn) {
	defer func(ws *websocket.Conn) {
		ws.CloseHandler()

	}(ws)
	for {
		msg := make([]byte, 512)
		senderMsg := new(SenderMsg)
		_, msg, err := ws.ReadMessage()
		if err != nil {
			return
		}
		err = json.Unmarshal(msg, senderMsg)
		if err != nil {
			ws.WriteMessage(websocket.TextMessage, []byte("Request Data Format Is Wrong"))
			continue
		}
		//fmt.Printf("%+v\n", senderMsg)
		if senderMsg.Type == "point" {
			wsConn, ok := Hub[senderMsg.Receptor]
			if !ok {
				ws.WriteMessage(websocket.TextMessage, []byte("This User Is Not Online"))
				continue
			}
			wsConn.WriteMessage(websocket.TextMessage, msg)
		} else if senderMsg.Type == "group" {
			wsConns, ok := HubGroup[senderMsg.RoomId]
			if !ok {
				ws.WriteMessage(websocket.TextMessage, []byte("This Room Is Not Online"))
			} else {
				for _, wsConn := range wsConns {
					wsConn.WriteMessage(websocket.TextMessage, msg)
				}
			}
		} else {
			ws.WriteMessage(websocket.TextMessage, []byte("Unknown Msg Type"))
		}

	}

}

func main() {

	r := gin.Default()
	r.GET("/ws/pointChat", WsHandle)
	r.POST("/chat/join_group", JoinGroup)
	r.Run("127.0.0.1:80")
}
